package com.jrx.anytxn.param.service.investor.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jrx.anytxn.common.data.TxnRespCode;
import com.jrx.anytxn.common.exception.TxnException;
import com.jrx.anytxn.common.uitl.BeanMapping;
import com.jrx.anytxn.common.uitl.StringUtils;
import com.jrx.anytxn.i18n.response.TxnPage;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.dto.investor.FundTableReq;
import com.jrx.anytxn.param.dto.investor.FundTableRes;
import com.jrx.anytxn.param.dto.investor.PrInvestorTableRes;
import com.jrx.anytxn.param.entity.PrFundFactor;
import com.jrx.anytxn.param.entity.PrFundTable;
import com.jrx.anytxn.param.entity.PrInvestorTable;
import com.jrx.anytxn.param.mapper.ext.ExtPrFundFactorMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrFundTableMapper;
import com.jrx.anytxn.param.mapper.ext.ExtPrInvestorTableMapper;
import com.jrx.anytxn.param.service.investor.IFundTableService;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * 资金源表 业务接口实现
 *
 * @author 黄秋平
 * @date 2020-5-14 10:27:46
 */
@Service
@CacheConfig(cacheNames = "FUND_TABLE")
public class FundTableServiceImpl implements IFundTableService {

    private static final Logger logger = LoggerFactory.getLogger(FundTableServiceImpl.class);

    @Resource
    private ExtPrFundTableMapper extPrFundTableMapper;

    @Resource
    private ExtPrFundFactorMapper extPrFundFactorMapper;

    @Resource
    private ISegmentService segmentService;

    @Resource
    private ExtPrInvestorTableMapper extPrInvestorTableMapper;

    @Override
    public TxnPage<FundTableRes> findAllPageByTenId(Integer pageNum, Integer pageSize,String tenantId) throws TxnException {
        Page<PrFundTable> page = PageHelper.startPage(pageNum, pageSize,Constant.ORDER_BY_SORT);
        List<PrFundTable> fundTableList = extPrFundTableMapper.selectByTenId(tenantId,null);
        if (fundTableList.isEmpty()) {
            logger.error("查询资金源列表不存在");
            throw new TxnException(TxnRespCode.NO_DATA.getMsg());
        }
        List<FundTableRes> res = BeanMapping.copyList(fundTableList, FundTableRes.class);
        return new TxnPage<>(pageNum, pageSize, page.getTotal(), res);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FundTableRes addFundTable(FundTableReq fundTableReq) throws TxnException {
        PrFundTable prFundTable = BeanMapping.copy(fundTableReq, PrFundTable.class);
        /*根据机构号ID和资金源ID查看数据库表里是否已存在此信息,若存在抛出异常*/
        PrFundTable fundTable = extPrFundTableMapper.selectByTenIdAndFundId(prFundTable.getTenantId(), prFundTable.getFundId());
        if (fundTable != null) {
            logger.error("机构号为{}与资金源ID为{}的信息已存在", prFundTable.getOrganizationId(), prFundTable.getFundId());
            throw new TxnException(TxnRespCode.DATA_EXISTS, TxnRespCode.DATA_EXISTS.getMsg());
        }
        /*查看此资金源下的出资方id是否相同*/
        List<PrFundFactor> prFundFactorList = fundTableReq.getControllerReqList();
        Set<PrFundFactor> set = new TreeSet<>((o1, o2) -> {
            //0==表示重复
            int compareToResult = 1;
            if (o1.getInvestorId().equalsIgnoreCase(o2.getInvestorId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(prFundFactorList);
        if (new ArrayList<>(set).size() != prFundFactorList.size()) {
            logger.error("出资方ID重复");
            throw new TxnException("出资方ID不能重复！");
        }
        /*增加或复制资金源信息*/
        try {
            prFundTable.setId(segmentService.getId(Constant.PR_FUND_TABLE));
        } catch (SegmentException e) {
            logger.error("主键生成错误",e);
            throw new TxnException(ErrorMsgConstant.ERROR_ID);
        }
        prFundTable.setRecordVersionNumber(Constant.VERSION_NUMBER);
        extPrFundTableMapper.insertSelective(prFundTable);

        /*增加或复制资金源出资方表信息*/
        List<PrFundFactor> list = fundTableReq.getControllerReqList();
        for (PrFundFactor factor : list) {
            try {
                factor.setId(segmentService.getId(Constant.PR_FUND_FACTOR));
            } catch (SegmentException e) {
                logger.error("主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            factor.setTenantId(fundTableReq.getTenantId());
            factor.setUpdateBy(fundTableReq.getUpdateBy());
            factor.setFundId(fundTableReq.getFundId());
            factor.setOrganizationId(fundTableReq.getOrganizationId());
            factor.setRecordVersionNumber(Constant.VERSION_NUMBER);
            extPrFundFactorMapper.insertSelective(factor);
        }

        return BeanMapping.copy(prFundTable, FundTableRes.class);
    }

    @Override
    @CacheEvict(key = "'fundTable_'+#fundTableReq.tenantId+'_'+#fundTableReq.fundId")
    @Transactional(rollbackFor = Exception.class)
    public FundTableRes modifyFundTable(FundTableReq fundTableReq) throws TxnException {
        PrFundTable prFundTable = BeanMapping.copy(fundTableReq, PrFundTable.class);
        /*查看此资金源下的出资方id是否相同*/
        List<PrFundFactor> prFundFactorList = fundTableReq.getControllerReqList();
        Set<PrFundFactor> set = new TreeSet<>((o1, o2) -> {
            //0==表示重复
            int compareToResult = 1;
            if (o1.getInvestorId().equalsIgnoreCase(o2.getInvestorId())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(prFundFactorList);
        if (new ArrayList<>(set).size() != prFundFactorList.size()) {
            logger.error("出资方ID重复");
            throw new TxnException("出资方ID不能重复！");
        }

        // 更新资金源表数据
        extPrFundTableMapper.updateByPrimaryKeySelectiveAndNotNull(prFundTable);
        // 更新资金源出资方表数据（先删后加）
        PrFundFactor prFundFactor = new PrFundFactor();
        prFundFactor.setTenantId(prFundTable.getTenantId());
        prFundFactor.setFundId(prFundTable.getFundId());
        List<PrFundFactor> factorTableList = extPrFundFactorMapper.selectByFundIdAndTenId(prFundFactor.getFundId(), prFundFactor.getTenantId());
        if (factorTableList != null && !factorTableList.isEmpty()) {
            for (PrFundFactor factorTable : factorTableList) {
                extPrFundFactorMapper.deleteByFundIdAndTenId(factorTable.getFundId(),factorTable.getTenantId());
            }
        }

        List<PrFundFactor> list = fundTableReq.getControllerReqList();
        for (PrFundFactor pr : list) {
            try {
                pr.setId(segmentService.getId(Constant.PR_FUND_FACTOR));
            } catch (SegmentException e) {
                logger.error("主键生成错误",e);
                throw new TxnException(ErrorMsgConstant.ERROR_ID);
            }
            pr.setTenantId(prFundTable.getTenantId());
            pr.setFundId(prFundTable.getFundId());
            pr.setOrganizationId(prFundTable.getOrganizationId());
            pr.setUpdateBy(prFundTable.getUpdateBy());
            pr.setRecordVersionNumber(prFundTable.getRecordVersionNumber()==null?1:prFundTable.getRecordVersionNumber());
            extPrFundFactorMapper.insertSelective(pr);
        }

        return BeanMapping.copy(prFundTable, FundTableRes.class);

    }

    @Override
    @CacheEvict(key = "'fundTable_'+#tenantId+'_'+#fundId")
    @Transactional(rollbackFor = Exception.class)
    public Boolean removeByFundIdAndTenId(String tenantId , String fundId) throws TxnException {
        if (StringUtils.isBlank(tenantId)||StringUtils.isBlank(fundId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }

        /*根据租户ID和资金源ID查询还款顺序表信息*/
        PrFundTable fundTable = extPrFundTableMapper.selectByTenIdAndFundId(tenantId,fundId);

        /*获取查询信息的资金源id和租户ID查询资金源出资方表里的相关信息列表*/
        PrFundFactor prFundFactor = new PrFundFactor();
        prFundFactor.setTenantId(fundTable.getTenantId());
        prFundFactor.setFundId(fundTable.getFundId());
        List<PrFundFactor> list = extPrFundFactorMapper.selectByFundIdAndTenId(prFundFactor.getFundId(), prFundFactor.getTenantId());
        if (list != null) {
            for (PrFundFactor pr : list) {
                extPrFundFactorMapper.deleteByFundIdAndTenId(pr.getFundId(), pr.getTenantId());
            }
        }
        int a = extPrFundTableMapper.deleteByTenIdAndFundId(tenantId, fundId);
        return a > 0;
    }

    @Override
    @Cacheable(key = "'fundTable_'+#tenantId+'_'+#fundId")
    public FundTableRes findByFundIdAndTenId(String tenantId , String fundId) throws TxnException {
        if (StringUtils.isBlank(tenantId)||StringUtils.isBlank(fundId)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }

        /*根据租户ID和资金源ID查询资金源表信息*/
        PrFundTable fundTable = extPrFundTableMapper.selectByTenIdAndFundId(tenantId,fundId);

        /*获取查询信息的资金源id和租户ID查询资金源出资方表里的相关信息列表*/
        PrFundFactor prFundFactor = new PrFundFactor();
        prFundFactor.setTenantId(fundTable.getTenantId());
        prFundFactor.setFundId(fundTable.getFundId());
        List<PrFundFactor> prFundFactorList = extPrFundFactorMapper.selectByFundIdAndTenId(prFundFactor.getFundId(), prFundFactor.getTenantId());
        FundTableRes res = BeanMapping.copy(fundTable, FundTableRes.class);
        res.setControllerReqList(prFundFactorList);
        return res;
    }

    @Override
    public List<PrFundTable> findAllByTenId(String tenantId) {
        List<PrFundTable> prFundTables = extPrFundTableMapper.selectByTenId(tenantId,Constant.STATUS_1);
        return BeanMapping.copyList(prFundTables, PrFundTable.class);
    }

    /**
     * 根据资金源id集合获取资金方id
     *
     * @param fundIds 资金源id
     * @param tenantId 租户id
     * @return List<PrFundFactor>
     * @throws TxnException
     * @author liuyang
     * @date 2020-6-9
     */
    @Override
    public List<PrFundFactor> findByFundIdsAndTenId(List<String> fundIds, String tenantId) throws TxnException {
        if (StringUtils.isBlank(tenantId)|| CollectionUtils.isEmpty(fundIds)) {
            logger.error(TxnRespCode.NOT_EMPTY.getMsg());
            throw new TxnException(TxnRespCode.NOT_EMPTY.getMsg());
        }
        List<PrFundFactor> fundFactors = extPrFundFactorMapper.selectByFundIdsAndTenId(fundIds,tenantId);
        return fundFactors;
    }

    @Override
    public List<PrInvestorTableRes> findInvestorByFundIdAndTenId(String tenantId, String fundId) throws TxnException {
        List<PrInvestorTableRes> investorTableResList=new ArrayList<>();
        List<PrFundFactor> fundFactorList=extPrFundFactorMapper.selectByFundIdAndTenId(fundId,tenantId);
        if(CollectionUtils.isNotEmpty(fundFactorList)){
            for (PrFundFactor prFundFactor:fundFactorList) {
                PrInvestorTableRes prInvestorTableRes=new PrInvestorTableRes();
                PrInvestorTable prInvestorTable= extPrInvestorTableMapper.selectByTenIdAndInvestorId(tenantId,prFundFactor.getInvestorId());
                prInvestorTableRes.setInvestorId(prFundFactor.getInvestorId());
                prInvestorTableRes.setChineseName(prInvestorTable.getChineseName());
                investorTableResList.add(prInvestorTableRes);
            }
        }
        return investorTableResList;
    }
}
